{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "24129119",
   "metadata": {},
   "source": [
    "# 深度学习入门 基于Python的理论和实现\n",
    "\n",
    "## 第二章 感知机\n",
    "\n",
    "感知机可以接收多个信号，输出一个信号。本书中输出为0或1，表示传递信号或者不传递信号，也就是神经元有没有激活。\n",
    "若x1, x2为输入，w1, w2为权重weight, theta为阈值，则\n",
    "$$\n",
    "f(n)\n",
    "\\begin{cases}\n",
    "0, &if\\  w1*x1 + w2*x2 \\le \\theta\\\\[3ex]\n",
    "1, &if\\  w1*x1 + w2*x2 \\gt \\theta\n",
    "\\end{cases}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81cf71cf",
   "metadata": {},
   "source": [
    "### 与门 AND gate\n",
    "真值表：\n",
    "\n",
    "|$x_1$|$x_2$|y|\n",
    "|:-:|:-:|:-:|\n",
    "|0|0|0|\n",
    "|1|0|0|\n",
    "|0|1|0|\n",
    "|1|1|1|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "925bd89a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 首先是与门 AND gate\n",
    "def AND(x1, x2):\n",
    "    w1, w2, theta = 0.5, 0.5, 0.7\n",
    "    if w1*x1 + w2*x2 <= theta:\n",
    "        return 0\n",
    "    else:\n",
    "        return 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "28bd7b5a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "0\n",
      "0\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "print(AND(0, 0)) # 输出0\n",
    "print(AND(1, 0)) # 输出0\n",
    "print(AND(0, 1)) # 输出0\n",
    "print(AND(1, 1)) # 输出0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "b32dbad6",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "def AND_np(x1, x2):\n",
    "    x = np.array([x1, x2])\n",
    "    w = np.array([0.5, 0.5])\n",
    "    b = -0.7 # 偏置\n",
    "    temp = np.sum(x*w) + b\n",
    "    if temp <= 0:\n",
    "        return 0\n",
    "    else:\n",
    "        return 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "0fdc0929",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "print(AND_np(1, 2)) # 输出1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03cb8415",
   "metadata": {},
   "source": [
    "### 与非门 NAND gate\n",
    "\n",
    "**`与门取反就是与非门`**\n",
    "\n",
    "真值表：\n",
    "\n",
    "|$x_1$|$x_2$|y|\n",
    "|:-:|:-:|:-:|\n",
    "|0|0|1|\n",
    "|1|0|1|\n",
    "|0|1|1|\n",
    "|1|1|0|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "65544b06",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 与非门 NAND gate\n",
    "\n",
    "def NAND_np(x1, x2):\n",
    "    x = np.array([x1, x2])\n",
    "    w = np.array([-0.5, -0.5])\n",
    "    b = 0.7\n",
    "    temp = np.sum(x*w) + b\n",
    "    if temp <= 0:\n",
    "        return 0\n",
    "    else:\n",
    "        return 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "1f64c15b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "print(NAND_np(0, 0)) # 输出1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "5b9e44e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 或门 OR\n",
    "\n",
    "def OR(x1, x2):\n",
    "    x = np.array([x1, x2])\n",
    "    w = np.array([0.5, 0.5])\n",
    "    b = -0.2\n",
    "    tmp = np.sum(w*x) + b\n",
    "    if tmp <= 0:\n",
    "        return 0\n",
    "    else:\n",
    "        return 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "561b5b6d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "1\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "print(OR(0, 0)) # 输出0\n",
    "print(OR(0, 1)) # 输出1\n",
    "print(OR(1, 0)) # 输出1\n",
    "print(OR(1, 1)) # 输出1\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bab9b840",
   "metadata": {},
   "source": [
    "### 异或门 XOR gate\n",
    "\n",
    "**`两个元素相同输出为0，不相同输出为1`**\n",
    "\n",
    "真值表：\n",
    "\n",
    "|$x_1$|$x_2$|y|\n",
    "|:-:|:-:|:-:|\n",
    "|0|0|0|\n",
    "|1|0|1|\n",
    "|0|1|1|\n",
    "|1|1|0|\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "319a9016",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 异或门 XOR gate\n",
    "# 采用多层感知机\n",
    "\n",
    "def XOR(x1, x2):\n",
    "    s1 = NAND_np(x1, x2)\n",
    "    s2 = OR(x1, x2)\n",
    "    y = AND(s1, s2)\n",
    "    return s1, s2, y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31d3a6aa",
   "metadata": {},
   "source": [
    "实际上感知机无法直接实现异或门，通过画图可以证明。\n",
    "\n",
    "\n",
    "![与或门](.\\\\picture\\\\capture-2022-12-24-22-01-06.png \"与或门\")\n",
    "\n",
    "所以我们采用多层感知机，先进行与非和或的运算，再用与门得到结果\n",
    "\n",
    "真值表：\n",
    "\n",
    "|$x_1$|$x_2$|$s_1$|$s_2$|y|\n",
    "|:-:|:-:|:-:|:-:|:-:|\n",
    "|0|0|1|0|0|\n",
    "|1|0|1|1|1|\n",
    "|0|1|1|1|1|\n",
    "|1|1|0|1|0|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "f0d4a3e7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 0, 0)\n",
      "(1, 1, 1)\n",
      "(1, 1, 1)\n",
      "(0, 1, 0)\n"
     ]
    }
   ],
   "source": [
    "print(XOR(0, 0)) # 输出100\n",
    "print(XOR(0, 1)) # 输出111\n",
    "print(XOR(1, 0)) # 输出111\n",
    "print(XOR(1, 1)) # 输出010"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "635289bf",
   "metadata": {},
   "source": [
    "### 总结\n",
    "<p>也就是说，感知机的形式都是一样的，但是可以表示不同的逻辑门。这里主要的区别就是配置权重。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
